﻿#region File and License Information
/*
<File>
	<License>
		Copyright © 2009 - 2017, Daniel Vaughan. All rights reserved.
		This file is part of Calcium (http://calciumsdk.net), 
		which is released under the MIT License.
		See file /Documentation/License.txt for details.
	</License>
	<CreationDate>2015-04-04 18:51:45Z</CreationDate>
</File>
*/
#endregion

using System;
using System.Reflection;
#if WINDOWS_PHONE
using System.Windows;
#endif

namespace Outcoder.Reflection
{
	public static class AssemblyExensions
	{
		/// <summary>
		/// Retrieves the <c>AssemblyBuildTime</c> for the specified assembly.
		/// <see cref="AssemblyBuildTime"/>
		/// </summary>
		public static AssemblyBuildTime GetBuildTime(this Assembly assembly)
		{
#if !WINDOWS_UWP && !NETFX_CORE
			if (assembly == null)
			{
				assembly = Assembly.GetCallingAssembly();
			}
#else
			ArgumentValidator.AssertNotNull(assembly, "assembly");
#endif
			return new AssemblyBuildTime(assembly.GetName().Version);
		}

#if !WINDOWS_UWP && !NETFX_CORE
		/// <summary>
		/// Retrieves the <c>AssemblyBuildTime</c> for the specified assembly version.
		/// <see cref="AssemblyBuildTime"/>
		/// </summary>
		public static AssemblyBuildTime GetBuildTime(this Version assemblyVersion)
		{
			if (assemblyVersion == null)
			{
				var assembly = Assembly.GetCallingAssembly();
				assemblyVersion = assembly.GetName().Version;
			}

			return new AssemblyBuildTime(assemblyVersion);
		}
#endif
	}

	/// <summary>
	/// This class allows you to retrieve a version number based on the build time of a specified assembly.
	/// </summary>
	public class AssemblyBuildTime
	{
		readonly Version version;
		readonly DateTime timeOfBuild;
		readonly long versionIdentifier;
		readonly string displayVersion;

		/// <summary>
		/// Initializes a new <c>AssemblyBuildTime</c> object using the specified version.
		/// If the provided assembly version is null, the version of the application's entry assembly is used.
		/// </summary>
		/// <param name="assemblyVersion">Can be null, if so the calling assembly version is used.</param>
#if WINDOWS_UWP || NETFX_CORE
		public AssemblyBuildTime(Version assemblyVersion)
		{
			ArgumentValidator.AssertNotNull(assemblyVersion, "assemblyVersion");
#else
		public AssemblyBuildTime(Version assemblyVersion = null)
		{
			if (assemblyVersion == null)
			{
				var assembly = Assembly.GetCallingAssembly();
				assemblyVersion = assembly.GetName().Version;
			}
#endif

			version = assemblyVersion;
			var startDate = new DateTime(2000, 01, 01);
			timeOfBuild = startDate.AddDays(version.Build).AddSeconds(version.Revision * 2);

			var difference = (timeOfBuild - startDate);

			versionIdentifier = (long)difference.TotalSeconds;

			var buildDateTime = new DateTime(2000, 1, 1).Add(new TimeSpan(
				TimeSpan.TicksPerDay * version.Build + // days since 1 January 2000
				TimeSpan.TicksPerSecond * 2 * version.Revision)); // seconds since midnight, (multiply by 2 to get original)

			var month = buildDateTime.Month;
			var day = buildDateTime.Day;
			var hour = buildDateTime.Hour;
			var minute = buildDateTime.Minute;

			displayVersion = string.Format("{0}.{1}.{2:D2}{3:D2}{4:D2}{5:D2}", 
				version.Major, version.Minor, month, day, hour, minute); //version.Build + "." + version.Revision;
		}

		//		static Assembly GetEntryAssembly()
		//		{
		//#if WINDOWS_PHONE
		//			var result = Application.Current.GetType().Assembly;
		//#else
		//			var result = Assembly.GetEntryAssembly();
		//#endif
		//			return result;
		//		}

#if !WINDOWS_UWP && !NETFX_CORE

		static AssemblyBuildTime entryBuildTime;

		/// <summary>
		/// Retrieves the <c>AssemblyBuildTime</c> of the application's entry assembly.
		/// </summary>
		public static AssemblyBuildTime EntryAssemblyBuildTime
		{
			get
			{
				if (entryBuildTime == null)
				{
					entryBuildTime = new AssemblyBuildTime();
				}

				return entryBuildTime;
			}
		}
#endif

		internal Version AssemblyVersion
		{
			get
			{
				return version;
			}
		}

		public string AssemblyFileVersion
		{
			get
			{
				return version.ToString();
			}
		}

		public string DisplayVersion
		{
			get
			{
				return displayVersion;
			}
		}

		public DateTime TimeOfBuild
		{
			get
			{
				return timeOfBuild;
			}
		}

		public long VersionIdentifier
		{
			get
			{

				return versionIdentifier;
			}
		}
	}

}
